package dao.impl.StoreDaoImpl;

import common.model.Entity.StoreEntity.Cart;
import dao.StoreDao.CartDao;
import common.util.DBUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Optional;

/**
 * 购物车数据访问接口实现类，提供购物车相关的数据库操作实现。
 *
 * <p>说明：
 * <ul>
 *   <li>所有“删除”均为逻辑删除（is_deleted = 1）。</li>
 *   <li>购物车本身不支持物理删除或统计数量，调用相关方法将抛出异常。</li>
 * </ul>
 *
 * @author your-name
 * @since 1.0
 */
public class CartDaoImpl implements CartDao {

    private static final Logger logger = LoggerFactory.getLogger(CartDaoImpl.class);
    private final QueryRunner queryRunner = new QueryRunner();

    /**
     * 根据用户 ID 查询购物车。
     *
     * @param userId 用户主键
     * @return 如果存在返回购物车，否则返回 {@link Optional#empty()}
     */
    @Override
    public Optional<Cart> findByUser(Long userId) {
        String sql = "SELECT id, user_id AS userId FROM t_cart WHERE user_id = ? ";
        try (Connection conn = DBUtil.getConnection()) {
            Cart cart = queryRunner.query(conn, sql, new BeanHandler<>(Cart.class), userId);
            return Optional.ofNullable(cart);
        } catch (SQLException e) {
            logger.error("根据用户ID查询购物车失败: userId={}", userId, e);
            return Optional.empty();
        }
    }

    /**
     * 保存购物车记录。
     *
     * @param cart 购物车实体，需包含 userId
     * @return 保存成功返回 true，否则返回 false
     */
    @Override
    public boolean save(Cart cart) {
        String sql = "INSERT INTO t_cart (user_id) VALUES (?)";
        try (Connection conn = DBUtil.getConnection()) {
            int affected = queryRunner.update(conn, sql, cart.getUserId());
            return affected > 0;
        } catch (SQLException e) {
            logger.error("保存购物车失败: userId={}", cart.getUserId(), e);
            return false;
        }
    }

    /**
     * 更新购物车时间戳。
     *
     * @param cart 购物车实体，需包含 id
     * @return 更新成功返回 true，否则返回 false
     */
    @Override
    public boolean update(Cart cart) {
        String sql = "UPDATE t_cart SET update_time = CURRENT_TIMESTAMP WHERE id = ? ";
        try (Connection conn = DBUtil.getConnection()) {
            int affected = queryRunner.update(conn, sql, cart.getId());
            return affected > 0;
        } catch (SQLException e) {
            logger.error("更新购物车失败: id={}", cart.getId(), e);
            return false;
        }
    }

    /**
     * 清空指定用户的购物车。
     *
     * <p>逻辑删除该用户购物车下的所有购物车项，并更新购物车时间戳。
     *
     * @param userId 用户主键
     * @return 操作成功返回 true，否则返回 false
     */
    @Override
    public boolean clearCart(Long userId) {
        String deleteItemsSql = "UPDATE t_cart_item SET is_deleted = 1, updated_at = CURRENT_TIMESTAMP " +
                "WHERE cart_id IN (SELECT id FROM t_cart WHERE user_id = ? AND is_deleted = 0)";
        String updateCartSql = "UPDATE t_cart SET update_time = CURRENT_TIMESTAMP WHERE user_id = ? ";

        try (Connection conn = DBUtil.getConnection()) {
            conn.setAutoCommit(false);
            try {
                queryRunner.update(conn, deleteItemsSql, userId);
                int affected = queryRunner.update(conn, updateCartSql, userId);
                conn.commit();
                return affected > 0;
            } catch (SQLException e) {
                conn.rollback();
                throw e;
            } finally {
                conn.setAutoCommit(true);
            }
        } catch (SQLException e) {
            logger.error("清空购物车失败: userId={}", userId, e);
            return false;
        }
    }

    /**
     * 根据主键查询购物车。
     *
     * @param id 购物车主键
     * @return 如果存在返回购物车，否则返回 {@link Optional#empty()}
     */
    @Override
    public Optional<Cart> findById(Long id) {
        String sql = "SELECT id, user_id AS userId FROM t_cart WHERE id = ? ";
        try (Connection conn = DBUtil.getConnection()) {
            Cart cart = queryRunner.query(conn, sql, new BeanHandler<>(Cart.class), id);
            return Optional.ofNullable(cart);
        } catch (SQLException e) {
            logger.error("根据ID查询购物车失败: id={}", id, e);
            return Optional.empty();
        }
    }

    /**
     * 查询所有购物车列表，按更新时间倒序排列。
     *
     * @return 购物车列表，若异常返回空列表
     */
    @Override
    public List<Cart> findAll() {
        String sql = "SELECT id, user_id AS userId FROM t_cart ORDER BY update_time DESC";
        try (Connection conn = DBUtil.getConnection()) {
            return queryRunner.query(conn, sql, new BeanListHandler<>(Cart.class));
        } catch (SQLException e) {
            logger.error("查询所有购物车失败", e);
            return List.of();
        }
    }

    /**
     * 购物车不支持删除操作。
     *
     * @param id 购物车ID
     * @return 总是抛出 {@link UnsupportedOperationException}
     * @throws UnsupportedOperationException 购物车不支持删除
     */
    @Override
    public boolean deleteById(Long id) {
        throw new UnsupportedOperationException("购物车不支持删除操作");
    }

    /**
     * 购物车不支持统计数量操作。
     *
     * @return 总是抛出 {@link UnsupportedOperationException}
     * @throws UnsupportedOperationException 购物车不支持count操作
     */
    @Override
    public long count() {
        throw new UnsupportedOperationException("购物车不支持count操作");
    }
}